import { Injectable } from '@nestjs/common';
import { CreateRechargeDto } from './dto/create-recharge.dto';
import { InjectRepository } from '@nestjs/typeorm';
import { Recharge } from './entities/recharge.entity';
import { Repository } from 'typeorm';
import { PageQuery } from '../../../util/entity/page.entity';
import { buildQuery } from '../../../util/common-fn';
import { UpdateRechargeDto } from './dto/update-recharge.dto';
import { User } from '../../admin/user/entities/user.entity';
import { Money } from '../money/entities/money.entity';
import { RecordService } from '../record/record.service';
import { DictType } from '../../../util/enum/dict.enum';
import { DictSonService } from '../../admin/dict-son/dict-son.service';

@Injectable()
export class RechargeService {
  constructor(
    @InjectRepository(Recharge)
    private rechargeRepository: Repository<Recharge>,
    private recordService: RecordService,
    private dictSonService: DictSonService,
  ) {}

  create(createRechargeDto: CreateRechargeDto) {
    return this.rechargeRepository.save(createRechargeDto);
  }

  findAll(pageQuery: PageQuery<Recharge>) {
    return this.rechargeRepository.findAndCount(buildQuery(pageQuery));
  }

  findOne(id: number) {
    return this.rechargeRepository.findOneByOrFail({ id });
  }

  update(id: number, updateRechargeDto: UpdateRechargeDto) {
    return this.rechargeRepository.update({ id }, updateRechargeDto);
  }

  remove(id: number) {
    return this.rechargeRepository.softDelete({ id });
  }

  /**
   * 购买充值(交易)
   * @param id
   * @param userId
   */
  async buy(id: number, userId: number) {
    await this.rechargeRepository.manager
      .transaction(async (tr) => {
        const recharge = await tr.findOneByOrFail(Recharge, { id: id });
        const user = await tr.findOneOrFail(User, {
          where: { id: userId },
          relations: {
            moneys: true,
          },
        });
        // 找到用户付钱的类型,点券还是金币等等
        const userMoney = user.moneys.find(
          (item) => item.priceType === recharge.buyPriceType,
        );
        // 这是处理message
        const buyPriceTypeName = await this.dictSonService.getNameByCode(
          DictType.DnfPriceType,
          recharge.buyPriceType,
        );
        const rewardPriceTypeName = await this.dictSonService.getNameByCode(
          DictType.DnfPriceType,
          recharge.rewardPriceType,
        );
        const errorMessage = `花费${recharge.buyNum}${buyPriceTypeName},获得${recharge.rewardNum}${rewardPriceTypeName}`;
        if (userMoney.num >= recharge.buyNum) {
          // 减去消耗的货币
          await tr.decrement(
            Money,
            { id: userMoney.id },
            'num',
            recharge.buyNum,
          );
          // 通过充值获得货币的类型,找到用户的货币类型
          const money = await tr.findOneByOrFail(Money, {
            user: { id: userId },
            priceType: recharge.rewardPriceType,
          });
          // 增加获得的货币
          await tr.increment(
            Money,
            { id: money.id },
            'num',
            recharge.rewardNum,
          );
          return {
            errorMessage,
          };
        } else {
          // 钱不够
          throw new Error(`想要${errorMessage},但是钱不够啦.`);
        }
      })
      .then(async (result) => {
        await this.recordService.insertValues({
          user: { id: userId },
          success: 1,
          type: 2,
          errorMessage: result.errorMessage,
          recharge: { id },
        });
      })
      .catch(async (err: Error) => {
        await this.recordService.insertValues({
          user: { id: userId },
          success: 0,
          type: 2,
          recharge: { id },
          errorMessage: err.message,
        });
        throw new Error(err.message);
      });
  }
}
